#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "usermanager.h"
#include "cJSON.h"
#include "timer.h"
#include "user.h"
#include "upper.h"

static usermanager manager = {0};
static char* file_path = "./config/userconfig";

void cleanloginstate(void){
    int i;
    for(i=0;i<MAX_USER_COUNT;i++){
        manager.users[i].logined = 0;
    }
}

static void saveconfig(){
    FILE* fp;
    fp = fopen(file_path,"wb+");
    if(fp){
        fwrite(&manager.users,sizeof(manager.users),1,fp);
        fclose(fp);
    }
}

void defaultuser(){
    strcpy(manager.users[0].username,"root");
    strcpy(manager.users[0].password,"123456");
    manager.users[0].valid = 1;
    strcpy(manager.users[1].username,"user1");
    strcpy(manager.users[1].password,"123456");
    manager.users[1].valid = 1;
    strcpy(manager.users[2].username,"user2");
    strcpy(manager.users[2].password,"123456");
    manager.users[2].valid = 1;
    strcpy(manager.users[3].username,"user3");
    strcpy(manager.users[3].password,"123456");
    manager.users[3].valid = 1;
    strcpy(manager.users[4].username,"user4");
    strcpy(manager.users[4].password,"123456");
    manager.users[4].valid = 1;
    strcpy(manager.users[5].username,"user5");
    strcpy(manager.users[5].password,"123456"); 
    manager.users[5].valid = 1;   
}

static void load_config(){
    FILE* fp;
    memset(&manager,0,sizeof(manager));
    if((fp = fopen(file_path,"r")) == NULL){
        printf("userconfig file open failed!\n");
        defaultuser();
        fp = fopen(file_path,"w+");
        if(fp){
            fwrite(&manager.users,sizeof(manager.users),1,fp);
            fclose(fp);
        }
    }
    else{
        printf("userconfig file success!\n");
        fread(&manager.users,sizeof(manager.users),1,fp);
        fclose(fp);
    }
}

void init_usermanager(void){    
    //读取配置文件，如果没有配置文件，就生成一个默认用户root,密码123456
    load_config();
    cleanloginstate();
}

cJSON* usermanager_packet(CMD_ID id,int returnCode){
    return response_packet(id,returnCode,NULL,0);
}

int userlogin(char* username,char* password,user_socket* p_user){
    int i;
    if(manager.logins >= MAX_LOGINS) return ERROR_MORE_THAN_MAX_LONINS;
    for(i=0;i<MAX_USER_COUNT;i++){
        if(manager.users[i].valid){
            if(strcmp(manager.users[i].username,username) == 0){
                if(strcmp(manager.users[i].password,password)){
                    return ERROR_PASSWORD_WRONG;
                }
                if(manager.users[i].logined == 1){
                    return ERROR_ALREADY_LOGGED;
                }
                if(p_user && p_user->username){                    
                    return ERROR_ALREADY_LOGGED;
                }
                manager.users[i].logined = 1;
                manager.logins ++;
                add_to_user_array(p_user,manager.users[i].username);
                return NO_ERROR;
            }
        }
        
    }
    return ERROR_NO_FIND_USER;
}

int userloginout(char* username,user_socket* p_user){
    int i;
    if(username == NULL || p_user->username == NULL) return ERROR_NO_FIND_USER;
    if(strcmp(p_user->username,username)){
        if(strcmp(p_user->username,"root")){
            return ERROR_NO_AUTHORITY;
        }
    }
    for(i=0;i<MAX_USER_COUNT;i++){
        if(manager.users[i].valid){
            if(strcmp(manager.users[i].username,username) == 0){
                if(manager.users[i].logined == 0) return ERROR_USER_NO_LOGINED;
                manager.users[i].logined = 0;
                manager.logins --;
                return NO_ERROR;
            }
        }
    }
    return ERROR_NO_FIND_USER;
}

int adduser(char* username,char* password,user_socket* p_user){
    int len = 0,i;
    if(strcmp(p_user->username,"root") == 0){
        for(i=0;i<MAX_USER_COUNT;i++){
            if(manager.users[i].valid == 0){
                break;
            }                
        }
        if(i == MAX_USER_COUNT) return ERROR_MAXED_USER_COUNT;
        len = strlen(username);
        if(len == 0 || len > USER_NAME_LENGTH) return ERROR_USERNAME_OVERLENGTH;
        len = strlen(password);
        if(len == 0 || len > PWD_LENGTH) return ERROR_PASSWORD_OVERLENGTH;
        strcpy(manager.users[i].username,username);
        strcpy(manager.users[i].password,password);
        manager.users[i].valid = 1;
        saveconfig();
        return NO_ERROR;
    }
    return ERROR_NO_AUTHORITY;
}

int deluser(char* username,user_socket* p_user){
    int len = 0,i;
    if(strcmp(p_user->username,"root") == 0){
        if(strcmp(username,"root") == 0) return ERROR_CANNOT_DELROOT;
        for(i=0;i<MAX_USER_COUNT;i++){
            if(manager.users[i].valid == 1){
                if(strcmp(manager.users[i].username,username) == 0){
                    manager.users[i].valid = 0;
                    manager.users[i].logined = 0;
                    saveconfig();
                    return NO_ERROR;
                }                
            }                
        }
    }
    return ERROR_NO_AUTHORITY;    
}

int changepwd(char* username,char* oldpassword,char* newpassword,user_socket* p_user){
    int i;
    if(strcmp(p_user->username,username)){
        if(strcmp(p_user->username,"root")){
            return ERROR_ONLY_CHANGESELF;
        }
    }
    if(strlen(newpassword) > PWD_LENGTH) return ERROR_PASSWORD_OVERLENGTH;
    for(i=0;i<MAX_USER_COUNT;i++){
        if(manager.users[i].valid == 1){
            if(strcmp(manager.users[i].username,username) == 0){
                if(strcmp(manager.users[i].password,oldpassword) == 0){
                    strcpy(manager.users[i].password,newpassword);
                    saveconfig();
                    return NO_ERROR;
                }
                return ERROR_PASSWORD_WRONG;              
            }
        }
    }
    return ERROR_NO_FIND_USER;
}

cJSON* usermanager_parse(CMD_ID id,cJSON* param,user_socket* p_user){
    char param1[64] = {0};
    char param2[64] = {0};
    char param3[64] = {0};
    cJSON* item;
    int ret = ERROR_USER_UNKNOWN_ID;
    switch(id){
        case id_user_login:
            item = cJSON_GetObjectItem(param,"userName");
            if(item){
                strcpy(param1,item->valuestring);
            }
            item = cJSON_GetObjectItem(param,"password");
            if(item){
                strcpy(param2,item->valuestring);
            }
            item = cJSON_GetObjectItem(param,"date");
            if(item){
                update_date(item->valuestring);
            }                   
            ret = userlogin(param1,param2,p_user);      
        break;
        case id_user_loginout:	
            item = cJSON_GetObjectItem(param,"username");
            if(item){
                strcpy(param1,item->valuestring);
            }
   
            ret = userloginout(param1,p_user);   
        break;
        case id_user_changepwd:
            item = cJSON_GetObjectItem(param,"username");
            if(item){
                strcpy(param1,item->valuestring);
            }
            item = cJSON_GetObjectItem(param,"oldpassword");
            if(item){
                strcpy(param2,item->valuestring);
            } 
            item = cJSON_GetObjectItem(param,"newpassword");
            if(item){
                strcpy(param3,item->valuestring);
            }        
            ret = changepwd(param1,param2,param3,p_user);      
        break;        
        default:
            break;

    }
    return usermanager_packet(id,ret);
}